package org.xx.armory.rpc;

import org.apache.commons.lang3.tuple.Pair;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.xx.armory.bindings.BoundParamCollection;
import org.xx.armory.bindings.ParamAnnotation;
import org.xx.armory.bindings.RawContent;
import org.xx.armory.commons.AbstractLifeCycle;
import org.xx.armory.commons.BuilderUtils;
import org.xx.armory.commons.LifeCycle;
import org.xx.armory.config.ConfigurationManager;
import org.xx.armory.rpc.routing.DeprecatedClassMethodException;
import org.xx.armory.rpc.routing.NoClassMethodException;
import org.xx.armory.rpc.routing.RouteData;
import org.xx.armory.rpc.routing.RouteTable;
import org.xx.armory.rpc.routing.RouteTable.MatchResult;
import org.xx.armory.service.Invocation;
import org.xx.armory.service.ServiceContext;
import org.xx.armory.service.ServiceException;
import org.xx.armory.service.ServiceNotAccessibleException;
import org.xx.armory.service.ServiceNotFoundException;
import org.xx.armory.service.SystemService;
import org.xx.armory.service.TempFileObject;

import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static java.lang.Runtime.getRuntime;
import static java.util.Collections.emptyMap;
import static java.util.concurrent.CompletableFuture.runAsync;
import static org.apache.commons.lang3.StringUtils.containsIgnoreCase;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;
import static org.xx.armory.commons.SysUtils.read;
import static org.xx.armory.commons.Validators.greaterThanOrEqual;
import static org.xx.armory.commons.Validators.notBlank;
import static org.xx.armory.commons.Validators.notNull;
import static org.xx.armory.commons.Validators.validIndex;
import static org.xx.armory.http.HttpUtils.decodeFormEncoded;
import static org.xx.armory.service.ServiceContext.ROUTE_KEY;

/**
 * 使用Restful协议的HTTP请求处理器。
 *
 * @author Haart
 */
public final class RpcHandler
        extends AbstractLifeCycle
        implements LifeCycle {
    private final Logger logger = LoggerFactory.getLogger(RpcHandler.class);
    private final RouteTable routeTable;
    private final List<Decorator> decorators;
    private volatile int parallelism;
    private volatile ServiceExecutor executor;

    /**
     * 构造{@code RpcHandler}对象的实例。
     */
    public RpcHandler() {
        this.decorators = new ArrayList<>(32);
        this.routeTable = new RouteTable();
        this.executor = null;
    }

    /**
     * 整理并简化{@link Throwable}对象。
     * <ol>
     * <li>如果t是{@link Error}，那么直接抛出该错误，因为错误无法被简化，必须第一时间抛出。</li>
     * <li>如果t是{@link RuntimeException}，那么也直接抛出，因为运行时异常不需要简化。</li>
     * <li>否则包装为{@link IllegalStateException}返回，因为未处理的CheckedException表示程序已运行到了无效状态。</li>
     * </ol>
     * </li>
     * </ol>
     *
     * @param t
     *         待简化的{@link Throwable}对象。
     * @return 简化后的结果。
     * @throws Error
     *         简化过程中遇到了Error。
     * @throws IllegalArgumentException
     *         如果参数{@code t}是{@code null}。
     */
    private static RuntimeException reduceThrowable(
            Throwable t
    ) {
        notNull(t, "t");

        if (t instanceof Error) {
            throw (Error) t;
        } else if (t instanceof RuntimeException) {
            throw (RuntimeException) t;
        } else {
            // 剩下的都是受检异常，包装为无效状态异常。
            return new IllegalStateException("unhandled exception", t);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final void initialize()
            throws Exception {
        super.initialize();

        // 读取修饰器栈。
        List<Decorator> decorators = ConfigurationManager.getConfiguration().getService()
                                                         .getDecorators()
                                                         .stream()
                                                         .map(s -> (Decorator) BuilderUtils.build(s.getClassName(), s.getFactoryName(), s.properties()))
                                                         .collect(Collectors.toList());
        // 依次初始化每个修饰器。
        for (final Decorator decorator : decorators) {
            decorator.initialize();
        }

        this.decorators.addAll(decorators);

        // 创建执行器。
        this.executor = new ServiceExecutor(this.parallelism);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public final void dispose()
            throws Exception {
        // 关闭执行器。
        this.executor.shutdown();
        if (!this.executor.awaitTermination(500, TimeUnit.MILLISECONDS)) {
            this.executor.shutdownNow();
        }

        // 依次清理每个修饰器。
        for (final Decorator decorator : this.decorators) {
            decorator.dispose();
        }

        super.dispose();
    }

    /**
     * 获取路由表。
     *
     * @return 路由表。
     */
    public final RouteTable getRouteTable() {
        return this.routeTable;
    }

    /**
     * 设置路由表。
     *
     * @param routeTable
     *         路由表。
     * @throws IllegalArgumentException
     *         如果参数{@code routeTable}是{@code null}。
     * @throws IllegalStateException
     *         如果处理器已被初始化。
     */
    public final void setRouteTable(
            RouteTable routeTable
    ) {
        notNull(routeTable, "routeTable");

        assertNotInitialized();

        this.routeTable.addAll(routeTable);
    }

    /**
     * 获取当前的工作线程集合。
     *
     * @return 当前的工作线程集合。
     */
    public final List<WorkThreadInfo> getWorkThreads() {
        return this.executor.getWorkThreads()
                            .stream()
                            .map(WorkThreadInfo::new)
                            .collect(Collectors.toList());
    }

    /**
     * 获取最大并发数。
     *
     * @return 最大并发数。
     */
    public final int getParallelism() {
        return this.parallelism;
    }

    /**
     * 设置最大并发数。
     *
     * <p>如果参数{@code parallelism}的值是0，那么用CPU核心的数目乘以2作为最大并发数。</p>
     *
     * @param parallelism
     *         最大并发数。
     * @throws IllegalStateException
     *         如果处理器已被初始化。
     * @see java.util.concurrent.Executors#newWorkStealingPool(int)
     */
    public final void setParallelism(
            int parallelism
    ) {
        assertNotInitialized();

        greaterThanOrEqual(parallelism, "parallelism", 0);

        if (parallelism == 0) {
            // 平均每个CPU核心承载2个线程。
            parallelism = getRuntime().availableProcessors() * 2;
        }

        this.parallelism = parallelism;
    }

    /**
     * 通过执行器处理RPC请求。
     *
     * @param request
     *         RPC请求对象。
     * @param response
     *         RPC响应对象。
     * @param serviceContext
     *         服务上下文。
     * @return 可完成的结果。
     * @throws IllegalArgumentException
     *         如果参数{@code request}或者{@code response}或者{@code serviceContext}是{@code null}。
     * @throws IllegalStateException
     *         如果处理器尚未初始化。
     */
    public CompletableFuture<Void> handle(
            RpcRequest request,
            RpcResponse response,
            ServiceContext serviceContext
    ) {
        assertInitialized();

        notNull(request, "request");
        notNull(response, "response");
        notNull(serviceContext, "serviceContext");

        if ("/!threads".equals(request.getPath())) {
            // 获取当前的线程信息。
            writeResult(request, response, new SystemService().threads(serviceContext));

            return CompletableFuture.completedFuture(null);
        }

        // 使用任务执行器运行业务逻辑代码。
        return runAsync(() -> processRequest(request, response, serviceContext), this.executor)
                .exceptionally(ex -> {
                    // 执行业务过程中出现异常，输出异常。
                    writeException(request, response, ex);
                    return null;
                });
    }

    /**
     * 处理RPC请求。
     *
     * @param request
     *         RPC请求对象。
     * @param response
     *         RPC响应对象。
     * @param serviceContext
     *         服务上下文。
     * @throws IllegalArgumentException
     *         如果参数{@code request}或者{@code response}或者{@code serviceContext}是{@code null}。
     * @throws ServiceNotFoundException
     *         如果无法根据HTTP请求找到可匹配的路由或者无法按照路由导入模块或方法。
     */
    private void processRequest(
            RpcRequest request,
            RpcResponse response,
            ServiceContext serviceContext
    ) {
        notNull(request, "request");
        notNull(response, "response");
        notNull(serviceContext, "serviceContext");

        // 获取请求路径（基于根路径）
        // 根据请求路径和HTTP方法从路由表中找到路由。
        final MatchResult matchResult = matchResult(request);
        if (matchResult != null) {
            logger.info("matched route for: {} => {}", request, matchResult.getRoute());

            // 根据路由加载类型和方法
            final String className = matchResult.getRoute().getClassName();
            final String methodName = matchResult.getRoute().getMethodName();
            final int[] permissions = matchResult.getRoute().getPermissions();

            serviceContext.put(ROUTE_KEY, matchResult.getRoute());

            final Class<?> clazz;
            final Method method;
            final Object obj;
            try {
                clazz = Class.forName(className);
                final Constructor<?> constructor = clazz.getConstructor();
                if (constructor == null) {
                    throw new NoClassMethodException(className, "<init>()");
                }
                constructor.setAccessible(true);
                obj = clazz.getConstructor().newInstance();
            } catch (ReflectiveOperationException ex) {
                // 匹配路由成功，但是通过路由创建对象时出错。
                throw new NoClassMethodException(className, methodName, ex);
            }

            method = importMethod(clazz, methodName);
            if (method == null) {
                // 匹配路由成功，但是通过路由查找方法时出错。
                throw new NoClassMethodException(className, methodName);
            }

            if (method.getDeclaredAnnotation(Deprecated.class) != null) {
                throw new DeprecatedClassMethodException(className, methodName);
            }

            final BoundParamCollection params = bindParams(method, matchResult.getRouteData(), request, serviceContext);
            serviceContext.put(ServiceContext.PARAMS_KEY, params);

            final Object result;
            try {
                result = createInvocation(request, response, obj, method, permissions).execute(params, serviceContext);
            } catch (Throwable ex) {
                throw reduceThrowable(ex);
            }

            // 执行业务过程中未发生任何异常，然后输出执行结果。
            writeResult(request, response, result);
        } else {
            throw new ServiceNotFoundException("no matched route " + request);
        }
    }


    /**
     * 输出业务执行结果。
     *
     * @param result
     *         待输出的业务执行结果。
     * @param request
     *         RPC请求。
     * @param response
     *         RPC响应。
     * @throws ResponseException
     *         如果向响应输出内容时出错。
     * @see RpcWriter#write(Object, RpcResponse)
     */
    private void writeResult(
            RpcRequest request,
            // TODO 通过RpcRequest判断是否需要启用缓存。
            RpcResponse response,
            Object result
    ) {
        if (result instanceof TempFileObject) {
            // TODO 通过验证码服务替换
            RpcWriters.writeTempFileObject(response, (TempFileObject) result);
        } else {
            RpcWriters.writeJson(response, result);
        }
    }

    /**
     * 输出业务执行过程中出现的异常。
     *
     * @param ex
     *         待输出的异常。
     * @param request
     *         RPC请求。
     * @param response
     *         RPC响应。
     * @throws ResponseException
     *         如果向response输出结果时出错。
     */
    private void writeException(
            RpcRequest request,
            RpcResponse response,
            Throwable ex
    ) {
        notNull(request, "request");
        notNull(response, "response");

        ex = unwrapException(notNull(ex, "ex"));

        if (ex instanceof ResponseException) {
            throw (RuntimeException) ex;
        } else if (ex instanceof IllegalArgumentException) {
            logger.error("illegal argument(s)", ex);
            response.badRequest();
        } else if (ex instanceof ServiceNotFoundException) {
            logger.error("cannot find service", ex);
            response.notFound();
        } else if (ex instanceof ServiceNotAccessibleException) {
            logger.error("cannot access service", ex);
            response.accessDenied();
        } else if (ex instanceof ServiceException) {
            logger.error("cannot execute service", ex);
            response.exception(ex);
        } else {
            final int requestIdentity = System.identityHashCode(request);
            final String tag = "$" + Integer.toHexString(requestIdentity) + "$";
            logger.error("runtime exception at request " + tag, ex);
            response.exception(new IllegalStateException(tag));
        }
    }

    /**
     * 解除异常包装。
     *
     * @param t
     *         包装异常。
     * @return 被包装的异常。
     */
    private Throwable unwrapException(
            Throwable t
    ) {
        if (t == null) {
            return null;
        } else if (t instanceof CompletionException) {
            return t.getCause();
        } else if (t instanceof InvocationTargetException) {
            return t.getCause();
        } else {
            return t;
        }
    }

    /**
     * 根据RPC请求尝试匹配路由。
     *
     * @param request
     *         RPC请求对象。
     * @return 匹配结果, 如果没有匹配的路由则返回{@code null}。
     * @throws IllegalArgumentException
     *         如果参数{@code request}是{@code null}。
     */
    private MatchResult matchResult(RpcRequest request) {
        if (request.getVerb() != RpcVerb.UNKNOWN) {
            return this.routeTable.find(request.getPath(), request.getVerb());
        } else {
            return null;
        }
    }

    /**
     * 根据方法名获取方法的元数据。
     * <p>
     * <strong>仅按照方法名从公开方法中查找, 不考虑方法的参数签名信息, 如果存在多个同名重载方法则只返回第一个匹配的方法。</strong>
     * </p>
     *
     * @param clazz
     *         方法所属的类型。
     * @param methodName
     *         方法名, 会被正规化, 不区分大小写。
     * @return 指定类型中具有指定方法名的方法元数据, 如果参数{@code clazz}是{@code null}或者找不到指定的方法则返回{@code null}。
     * @throws IllegalArgumentException
     *         如果参数{@code methodName}是{@code null}或者只包含空白字符。
     * @see Class#getMethods()
     */
    private Method importMethod(
            Class<?> clazz,
            String methodName
    ) {
        if (clazz != null) {
            methodName = notBlank(methodName, "methodName").trim();

            for (final Method method : clazz.getMethods()) {
                if (!methodName.equalsIgnoreCase(method.getName())) {
                    continue;
                }

                return method;
            }
        }

        return null;
    }

    /**
     * 绑定数据参数。
     *
     * @param moduleMethod
     *         待执行的方法，返回的绑定参数的类型必须和该方法的参数类型逐个匹配。
     * @param routeData
     *         匹配的路由数据。
     * @param request
     *         RPC请求对象。
     * @param serviceContext
     *         服务上下文。
     * @return 绑定的数据参数集合。
     */
    private BoundParamCollection bindParams(
            Method moduleMethod,
            RouteData routeData,
            RpcRequest request,
            ServiceContext serviceContext
    ) {
        final Class<?>[] paramTypes = moduleMethod.getParameterTypes();
        final Annotation[][] annotations = moduleMethod.getParameterAnnotations();

        // 判断此方法包含注解RawContent
        final RawContent rc = moduleMethod.getAnnotation(RawContent.class);
        if (rc == null) {
            // 不包含RawContent注解，那么从HTTP请求中解析表单数据。
            return bindFormParams(routeData, paramTypes, annotations, request, serviceContext);
        } else {
            // 包含注解，不再解析表单数据，而是直接从HTTP请求中获取全部原始数据。
            return bindRawParams(routeData, paramTypes, annotations, request, serviceContext);
        }
    }

    /**
     * 从路由数据和表单数据中获取映射到待执行的方法的参数值。
     *
     * @param routeData
     *         匹配的路由数据。
     * @param paramTypes
     *         参数类型数组。
     * @param annotations
     *         参数注解数组。
     * @param request
     *         RPC请求对象。
     * @param sctx
     *         服务上下文。
     * @return 绑定的数据参数集合。
     * @throws IllegalArgumentException
     *         如果参数{@code routeData}是{@code null}, 或者参数{@code request}是{@code null}， 或者参数
     *         {@code method}是{@code null}, 或者参数 {@code sctx}是{@code null}。
     */
    private BoundParamCollection bindFormParams(
            RouteData routeData,
            Class<?>[] paramTypes,
            Annotation[][] annotations,
            RpcRequest request,
            ServiceContext sctx
    ) {
        notNull(routeData, "routeData");
        notNull(paramTypes, "paramTypes");
        notNull(annotations, "annotations");
        notNull(request, "request");
        notNull(sctx, "ctx");

        final BoundParamCollection params = new BoundParamCollection();
        final Map<String, String> formData = getFormData(routeData, request);
        for (int i = 0; i < paramTypes.length; ++i) {
            final Class<?> paramType = paramTypes[i];

            if (paramType.isAssignableFrom(ServiceContext.class)) {
                params.put("__sctx__", sctx);
            } else {
                final Pair<String, Object> nv = bindParam(i, paramTypes[i], ParamAnnotation.of(annotations[i]), routeData, formData);
                params.put(nv.getKey(), nv.getValue());
            }
        }

        return params;
    }

    /**
     * 从路由数据和原始请求流中绑定原始数据参数，不使用表单（包括QueryString）。
     *
     * @param routeData
     *         匹配的路由数据。
     * @param paramTypes
     *         参数类型数组。
     * @param annotations
     *         参数注解数组。
     * @param request
     *         RPC请求对象。
     * @param sctx
     *         服务上下文。
     * @return 绑定的数据参数集合。
     */
    private BoundParamCollection bindRawParams(
            RouteData routeData,
            Class<?>[] paramTypes,
            Annotation[][] annotations,
            RpcRequest request,
            ServiceContext sctx
    ) {
        notNull(routeData, "routeData");
        notNull(paramTypes, "paramTypes");
        notNull(annotations, "annotations");
        notNull(request, "request");
        notNull(sctx, "ctx");

        byte[] bytes;
        try {
            bytes = read(request.getInputStream());
        } catch (IOException ex) {
            logger.warn("cannot read bytes from input stream");
            bytes = new byte[0];
        }

        final BoundParamCollection params = new BoundParamCollection();
        boolean bound = false; // 只绑定第一个byte[]类型的参数。
        for (int i = 0; i < paramTypes.length; ++i) {
            final Class<?> paramType = paramTypes[i];

            if (paramType.isAssignableFrom(ServiceContext.class)) {
                params.put("__sctx__", sctx);
            } else if (paramType.equals(byte[].class) && !bound) {
                bound = true;
                params.put("__" + i + "__", bytes);
            } else {
                final Pair<String, Object> nv = bindParam(i, paramTypes[i], ParamAnnotation.of(annotations[i]), routeData, emptyMap());
                params.put(nv.getKey(), nv.getValue());
            }
        }

        return params;
    }

    /**
     * 绑定单个数据参数。
     *
     * @param i
     *         参数的序号。
     * @param paramType
     *         参数的类型。
     * @param aa
     *         绑定注解。
     * @param routeData
     *         匹配的路由数据。
     * @param postFormData
     *         请求中的表单数据（包括QueryString中的数据）。
     * @return 绑定的参数值，已被转化为{@code paramType}的形式。
     * @throws IllegalArgumentException
     *         如果参数{@code paramType}或者{@code aa}或者{@code routeData}或者{@code postFormData}是
     *         {@code null}。
     */
    private Pair<String, Object> bindParam(
            int i,
            Class<?> paramType,
            ParamAnnotation aa,
            RouteData routeData,
            Map<String, String> postFormData
    ) {
        validIndex(i, "i");
        notNull(paramType, "paramType");
        notNull(aa, "aa");
        notNull(routeData, "routeData");
        notNull(postFormData, "postFormData");

        final String aname;
        final String avalue;
        if (aa.isBindable()) {
            // 如果该参数被注解为可以绑定，那么从路由数据或者表单中查找参数值。
            aname = aa.getName();
            avalue = getParamValue(aa, routeData, postFormData);
        } else {
            // 否则该参数的值是null或默认值。
            aname = "__" + i + "__";
            avalue = "";
        }

        return Pair.of(aname, ParamConverters.convert(avalue, paramType));
    }

    /**
     * 获取单个数据参数的字符串形式的值。
     *
     * @param aa
     *         绑定注解。
     * @param routeData
     *         匹配的路由数据。
     * @param postFormData
     *         请求中的表单数据（包括QueryString中的数据）。
     * @return 字符串形式的绑定的参数值，如果找不到指定的参数则返回空字符串，如果未标记为{@literal Text}则去掉首尾空格。
     * @throws IllegalArgumentException
     *         如果参数{@code aa}或者{@code routeData}或者{@code postFormData}是{@code null}。
     */
    private String getParamValue(
            ParamAnnotation aa,
            RouteData routeData,
            Map<String, String> postFormData
    ) {
        notNull(aa, "aa");
        notNull(routeData, "routeData");
        notNull(postFormData, "postFormData");

        // 首先从路由数据中查找参数值。
        String value = routeData.get(aa.getName(), null);
        // 如果找不到则从表单数据中查找参数值。
        if (value == null) {
            value = postFormData.get(aa.getName());
        }
        // 如果还找不到则取空字符串。
        if (value == null) {
            value = "";
        }

        // 没有文本参数的注解，需要去掉首尾空格。
        if (!aa.isText()) {
            value = trimToEmpty(value);
        }

        return value;
    }

    /**
     * 从RPC请求中解析表单数据。
     *
     * @param routeData
     *         请求相关的路由数据。
     * @param request
     *         RPC请求。
     * @return 解析得到的表单数据。
     * @throws NullPointerException
     *         如果参数{@code routeData}是{@code null}或者参数{@code request}是{@code null}。
     * @see org.xx.armory.http.HttpUtils#decodeFormEncoded(String)
     */
    private Map<String, String> getFormData(
            RouteData routeData,
            RpcRequest request
    ) {
        notNull(routeData, "routeData");
        notNull(request, "request");

        // 提交的表单数据。
        final Map<String, String> postFormData = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);

        // 首先解析查询字符串，并将结果存入表单数据。
        try {
            postFormData.putAll(decodeFormEncoded(request.getQueryString()));
        } catch (IOException ex) {
            logger.warn("cannot read parameters from query string", ex);
        }

        // 解析Request的Body部分，并将结果存入表单数据。
        // 如果此处的解析结果和查询字符串重复，那么会覆盖查询字符串的解析结果。
        switch (routeData.getRoute().getVerb()) {
            // 只有PUT, POST和DELETE方法需要解析Form。
            case PUT:
            case POST:
            case DELETE:
                // application/x-www-form-urlencoded
                if (containsIgnoreCase(request.getContentType(), "form-urlencoded")) {
                    try {
                        postFormData.putAll(decodeFormEncoded(request.getBody()));
                    } catch (IOException ex) {
                        logger.warn("cannot read parameters from form data", ex);
                    }
                }
            default:
        }

        return postFormData;
    }

    /**
     * 根据待执行的对象和待执行的方法创建执行器。
     *
     * @param request
     *         关联的RPC请求。
     * @param response
     *         关联的RPC响应。
     * @param obj
     *         待执行的对象。
     * @param method
     *         待执行的方法。
     * @param permissions
     *         执行此方法所需的权限数组。
     * @return 可以和修饰器一起运行的执行器。
     * @throws IllegalArgumentException
     *         如果参数{@code request}或者{@code response}或者{@code obj}或者{@code method}或者{@code permissions}是{@code null}。
     */
    private Invocation createInvocation(
            RpcRequest request,
            RpcResponse response,
            Object obj,
            Method method,
            int[] permissions
    ) {
        notNull(request, "request");
        notNull(response, "response");
        notNull(obj, "obj");
        notNull(method, "method");
        notNull(permissions, "permissions");

        // 构造修饰器栈。
        final Deque<Decorator> decorators = new ArrayDeque<>(this.decorators);

        return new Invocation() {
            /**
             * {@inheritDoc}
             */
            @Override
            public RpcRequest getRequest() {
                return request;
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public RpcResponse getResponse() {
                return response;
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public Object getObject() {
                return obj;
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public Method getMethod() {
                return method;
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public int[] getPermission() {
                return permissions;
            }

            /**
             * {@inheritDoc}
             */
            @Override
            public Object execute(
                    BoundParamCollection params,
                    ServiceContext serviceContext
            )
                    throws Throwable {
                // 从修饰器栈中获取下一个。
                final Decorator decoration = decorators.poll();

                if (decoration != null) {
                    // 如果存在则调用修饰器。
                    return decoration.execute(this, params, serviceContext);
                } else {
                    // 否则执行Bean的方法。
                    try {
                        return method.invoke(obj, params.values().toArray());
                    } catch (InvocationTargetException ex) {
                        throw ex.getTargetException();
                    }
                }
            }
        };
    }
}
